package com.kt.coroutinedemo.utils

import android.util.Log

import com.streamax.app.cqbus.platform.ext.capture
import com.streamax.app.cqbus.platform.ext.toBcdWordInt6
import com.streamax.app.cqbus.platform.ext.toByteArray

import com.streamax.app.cqbus.platform.ext.toInt
import com.streamax.app.cqbus.platform.ext.toInt2
import com.swallowsonny.convertextlibrary.toHexString
import java.nio.charset.Charset

/**
 * 解包工具
 */

object DecodeUtils {

    /**
     *  Byte转整形
     */
    fun bytesToInteger16(bytes: ByteArray?, pos: Int, length: Int): Int {
        if (bytes == null || bytes.size == 0 || pos < 0 || length < 0 || length > 4) {
            Log.e(
                    "CodeConvert",
                    "bytesToInteger param bytes=" + bytes + "pos=" + pos + "length=" + length
            )
        }
        var value = 0
        for (i in 0 until length) {
            val temp = bytes!![pos + i].toInt() and 255
            value = value or (temp shl i * 8)
        }
        return value.toByteArray.toHexString(false).toInt()
    }


    /**
     * 解码日期
     */
    fun decodeDateTime(date: ByteArray): DateTime =
        DateTime(date)

    /**
     * 解码里程
     */
    fun decodeMileage(buffer: ByteArray): Float? {
        if (buffer.size != 3) null
        val res = "${buffer[0].toInt()}${buffer[1].toInt()}.${buffer[2].toInt()}"
        return res.toFloat()
    }


    /**
     * TODO 解析基础包
     *
     * @param buffer
     * @param length
     */
    fun baseEnPackage(buffer: ByteArray): BaseCommand {
        var baseCommand = BaseCommand()
        //如果空包，或者长度小于基础的11时，则不解析
        if (buffer == null || buffer.size < 11) {
            return baseCommand
        }
        //帧长度
        val len: Int = buffer.capture(3, 4).toInt2
        if (len < 0) {
            return baseCommand
        }
        //减去vip及帧尾和校验位,得数据长度
        baseCommand.length = (len - 4 - 1 - 1)
        //帧头
        var head = buffer[0].toString(16) + buffer[1].toString(16)
        //判断帧头
        if (!("2626").equals(head)) {
            return baseCommand
        }
        //解析帧尾
        var endOfData = buffer[len + 4].toString(16)
        if (!("b").equals(endOfData)) {
            return baseCommand
        }
        //解析命令Id
        var comand = (buffer[2].toInt() and 0xFF).toString(16)
        baseCommand.commandId = comand
        //VIP
        baseCommand.vip = String.format("%02X", buffer[5]) + String.format("%02X", buffer[6]) + String.format("%02X", buffer[7]) + String.format("%02X", buffer[8]);

        //把基础的数据移除后，将内容buffer给其他
        val startIndex = 9
        val endIndex = (len + 5) - 2 - 1//索引从0开始长度要减一
        // 检查索引是否有效
        require(startIndex >= 0 && endIndex < buffer.size) { "Index out of bounds" }
        // 使用sliceArray获取子ByteArray
        var content = buffer.sliceArray(startIndex..endIndex)
        baseCommand.content = content
        //命令序列号
        var snNum = PacketUtils.GetWord(content, 0);
        baseCommand.centerSnNum = snNum

        return baseCommand
    }

    /**
     * 解析TCP协议基础包
     */
    fun baseEnFilePackage(readData: ByteArray, baseFileCommand: BaseFileCommand) {
        var offset = 0
        //头
        val head = readData.capture(0, 0).toHexString(false) + readData.capture(1, 1).toHexString(false)
        //判断帧尾
//        val len = readData.capture(3,4).toInt2 //包长度
//        Log.e("DecodeUtils", "判断帧尾: ${(readData[4+len].toInt() and 0xFF).toString(16)}", )
//        if ("0${(readData[4+len].toInt() and 0xFF).toString(16).uppercase(Locale.ROOT)}" != "0B"){
//            throw Exception("帧尾错误")
//        }
        if (readData[readData.size-1].toInt() != 0x0B){
            throw Exception("帧尾错误:${readData[readData.size-1].toInt()}")
        }
        //判断检验位置
//        Log.e("DecodeUtils", "判断检验位置: ${PacketUtils.XorValue(readData,0,readData.size-3)} 检验位：${(readData[4+len-1].toInt() and 0xFF).toString(16)} ", )
//        if (PacketUtils.XorValue(readData,0,4+len-1) != readData[4+len-1]){
//            throw Exception("校验位错误")
//        }
        if (head == "2626"){
            //正确的包头
            offset+=2
            baseFileCommand.commandId = readData.capture(offset,offset).toInt //命令字
            offset+=1
            baseFileCommand.packetLen = readData.capture(offset,offset+1).toInt2 //包长度
            offset+=2
            baseFileCommand.terminalNum = readData.capture(offset,offset+5).toBcdWordInt6 //终端号
            offset+=6
            baseFileCommand.snNum = readData.capture(offset,offset+1).toInt2  //序列号
            offset+=2
            baseFileCommand.content = readData.capture(offset,readData.size-3)  //
        }else{
            throw Exception("帧头错误")
        }
    }

    /**
     * TODO ASCII码的字符串
     *
     * @param buffer
     * @param offset
     * @param length
     */
    fun ASCIIToString(buffer: ByteArray, offset: Int, length: Int): String {
        return String(buffer, offset, length, Charsets.US_ASCII)
    }

    /**
     * TODO 获取ip地址
     *
     * @param buffer
     * @param offset
     * @return
     */
    fun getIpAddress(buffer: ByteArray, offset: Int): String {
        return "${buffer.capture(offset, offset).toInt and 0xFF}.${buffer.capture(offset + 1, offset + 1).toInt and 0xFF}.${buffer.capture(offset + 2, offset + 2).toInt and 0xFF}.${buffer.capture(offset + 3, offset + 3).toInt and 0xFF}"
    }

    /**
     * TODO
     *
     * @param buffer
     * @param offset
     * @param length 当前数据的长度
     */
    fun getStringGBK(buffer: ByteArray, offset: Int, length: Int): String {
        val charset = Charset.forName("GBK")
        //获取buffer
        var bytes = buffer.copyOfRange(offset, offset + length)
        return String(bytes, charset)
    }

    /**
     * TODO 解析位置信息为数字显示
     *
     * @param buffer
     * @param offset
     * @return
     */
    fun getCoordinate(buffer: ByteArray, offset: Int): Double {
        var value: Double = 0.0
        try {
            var b1: Byte = buffer[offset]
            var b2: Byte = buffer[offset + 1]
            var b3: Byte = buffer[offset + 2]
            var b4: Byte = buffer[offset + 3]
            var degree: Int = String.format("%02d", b1).toInt()
            var minute: Double = (String.format("%02d", b2) + "." + String.format("%02d", b3) + String.format("%02d", b4)).toDouble()
            value = degree + minute / 60.0
        } catch (e: Exception) {

        }
        return value;
    }

    /**
     * TODO 获取海拔高度的数据
     *
     * @param buffer
     * @param offset
     * @return
     */
    fun getAltitude(buffer: ByteArray, offset: Int): UShort {
        var value = "${buffer[offset].toUInt()}${"%02d".format(buffer[offset + 1])}"
        return value.toUShort();
    }

    /**
     * TODO 获取时间(yyyy-MM-dd HH:mm:ss)
     *
     * @param buffer
     * @param offset
     * @return
     */
    fun getDateTime(buffer: ByteArray, offset: Int): String {
        try {
            var year = "20" + formatNumber(buffer[offset].toInt())
            var month = formatNumber(buffer[offset + 1].toInt())
            var day = formatNumber(buffer[offset + 2].toInt())
            var hour = formatNumber(buffer[offset + 3].toInt())
            var minite = formatNumber(buffer[offset + 4].toInt())
            var second = formatNumber(buffer[offset + 5].toInt())

            var sTime = "$year-$month-$day $hour:$minite:$second"

            return sTime
        } catch (e: Exception) {
            return ""
        }
    }

    /**
     * TODO 获取时间(HH:mm:ss)
     *
     * @param buffer
     * @param offset
     * @return
     */
    fun getTime(buffer: ByteArray, offset: Int): String {
        try {

            var hour = formatNumber(buffer[offset].toInt())
            var minite = formatNumber(buffer[offset + 1].toInt())
            var second = formatNumber(buffer[offset + 2].toInt())

            var sTime = "$hour:$minite:$second"

            return sTime
        } catch (e: Exception) {
            return ""
        }
    }

    fun formatNumber(number: Int): String {
        return if (number < 10) "0$number" else number.toString()
    }
}